La présente section vous montre comment écrire une extension pour Scribus. Les extensions sont des librairies qui sont chargées dans l'application principale au moment de l'exécution. Les extensions peuvent étendre, voire modifier le comportement de l'application sans nécessiter de réécriture ni de recompilation. Elles permettent d'ajouter des outils supplémentaires, de nouvelles fonctions d'importation et d'exportation, et plusieurs autres fonctionnalités évoluées.
Ce document présuppose une connaissance de base du langage C++. Vous devez savoir ce qu'est un fichier d'en-tête et comment fonctionne l'inclusion de fichier;aussi, vous devez posséder des connaissance sur l'héritage des classes et une certaine maîtrise du langage C++. La connaissance de Qt - principalement QString et QObject - sera également utile. Des questions comme les fonctions virtuelles et purement virtuelles, les déclarations "extern C", les détails de la gestion de mémoire, etc. sont éludées dans ce document. Vous n'avez pas à les connaître, mais elles pourraient vous aider à mieux suivre ce qui ce passe.
Nous n'allons pas tenter d'expliquer ici les détails du fonctionnement du système d'extensions de Scribus. Le présent document explique seulement comment écrire une extension. La documentation des texte d'aide scplugin.h
et pluginmanager.h
explique le fonctionnement du système.
Scribus est livré avec un certain nombre d'extensions standard. Celles-ci seront installées en même temps que le programme Scribus et ses autres fichiers. Sous UNIX, les extensions seront installées sous le même préfixe que l'application principale. Sous Mac OS X elles sont incluses avec l'application. Si vous voulez savoir ce que font ces extensions, le meilleur moyen de le découvrir est de démarrer Scribus et d'aller dans Fichier->Préférences
puis de cliquer sur l'icône "extensions". À partir de là, vous obtiendrez une liste des extensions installées, des types d'extensions associés et des emplacements des fichiers.
En plus des extensions livrées en standard avec Scribus, il est possible de compiler et d'installer des extensions obtenues ailleurs, ou d'écrire et d'ajouter la vôtre.
Supposons que vous avez eu une bonne idée pour améliorer Scribus et que vous êtes impatient d'écrire un code C++ de qualité. Patientez quelques minutes et lisez la présente section; vous pourriez gagner du temps et vous éviter des problèmes.
Peut-être que vous êtes sur le point de "réinventer la roue", c'est-à-dire de ré-écrire ce que quelqu'un d'autre a déjà fait. Vous devriez vous joindre à la liste de diffusion et afficher votre idée, ou vous connecter au canal #scribus
sur irc.freenode.net
. Votre sujet sera soumis à l'étude, et vous obtiendrez probablement de l'aide et des idées des développeurs et des utilisateurs. Comme Scribus est distribué sous licence libre, vous pouvez travailler en solitaire, mais vous devriez au moins avoir une conversation d'introduction sur IRC ou envoyer un courriel à la liste de diffusion, ce qui pourrait vous éviter des heures de travail et des maux de tête. Nous voulons faciliter l'écriture d'extensions le plus possible pour les personnes intéressées.
Scribus n'a pas une API fixe en C++ pour accommoder les extensions. Les versions ne sont pas compatibles en binaire, et les versions instables enfreignent souvent la compatibilité avec le code source. La compatibilité source n'est pas garantie actuellement, même entre des versions stables, lorsque des changements sont requis pour corriger un problème. Nous espérons redresser la situation dans l'avenir et fournir une API C++ stable pour le code externe. Pour l'instant, vous devez tenter d'intégrer l'essentiel de vos fonctionnalités dans un module séparé qui dépend le moins possible des rouages internes de Scribus.
Ce document traite de la mise en oeuvre d'une extension pour Scribus 1.3.1cvs. Les exigences sont radicalement différentes de celles des versions 1.2.x. Les changements futurs devraient être moins importants.
Il est peu pratique de prévoir l'écriture d'une extension pouvant fonctionner sous les versions 1.2.x et 1.3.x de Scribus.
Il n'est pas trop difficile de se mettre à écrire une extension. La documentation ci-dessous décrit l'implantation d'une extension et vous renvoie à des compléments d'information au besoin. Un "modèle d'extension" vous est fourni, et vous pouvez en faire une copie au moment de débuter la programmation. Des instructions de base sont incluses dans le fichier et, en cas doute, vous pouvez consulter ce document.
Nous allons bâtir l'extension comme un composant de Scribus. C'est la manière la plus simple de commencer, même si vous prévoyez de la distribuer séparément plus tard (voir plus loin). Pour commencer à travailler sur une extension (de type Action) :
scribus/plugins/myplugin
dans scribus/plugins/pluginname
(où "pluginname" est le nom que vous voulez donner à votre extension).
pluginname doit être un identifiant C valide - je suggère d'utiliser seulement les caractères minuscules.scribus/plugins/Makefile.am
et ajoutez "pluginname" à Makefile.am. Cela indique au système d'intégration de Scribus de compiler votre extension.scribus/plugins/pluginname/
de myplugin
en pluginname
, par exemple
myplugin.h
en pluginname.h
.
Ne renommez pas Makefile.am.myplugin
là où il figure dans les fichiers en
pluginname
, par exemple myplugin_getPluginAPIVersion()
en pluginname_getPluginAPIVersion()
. Faites de même pour
MyPlugin
et MYPLUGIN
. Sous UNIX, vous pouvez utiliser cette commande :sed -i -e "s/myplugin/pluginname/g" -e "s/MyPlugin/PluginName/g" -e "s/MYPLUGIN/PLUGINNAME/g" myplugin*
scribus/plugins/pluginname/
).
Vous êtes maintenant prêt à commencer à travailler sur votre extension. Premièrement, vous devez entrer des renseignements à propos de votre extension dans pluginname.cpp
:
PluginName::languageChange()
:
m_actionInfo.text
pour le texte de l'élément de menu qui doit lancer votre extension.m_actionInfo.menu
pour le nom du menu qui doit afficher cet élément. Voir FIXME where????
FIXME pour une liste de noms de menu.m_actionInfo.keySequence
et inscrivez-y votre raccourci préféré. L'exemple ci-dessousdevrait vous montrer comment cela fonctionne.PluginName::fullTrName()
pour le nom de votre extension tel que vous voulez qu'il figure à l'écran Aide->À propos des extensions et dans le panneau de gestion des extensions (dans les préférences).À propos
. Pour connaître l'information possible, consultez la définition de AboutData
dans scplugin.h
.Vous avez terminé la mise en place de l'extension et vous pouvez maintenant commencer à programmer. Votre code
doit être placé dans pluginnameimpl.cpp
et
pluginnameimpl.h
. Le code existant devrait afficher une boîte de dialogue contenant un message.
Pour compiler l'extension, il suffit d'exécuter une nouvelle fois make -f Makefile.cvs
, ./configure
, et make
dans le répertoire supérieur de Scribus.
Une fois la compilation terminée, exécutez make install
et démarrez Scribus.
Votre extension doit maintenant figurer dans le gestionnaire d'extensions (dans les préférences) et doit être associée à un élément de menu. Si vous appuyez sur l'élément de menu, vous devriez obtenir une boîte de dialogue.
Attention, il est facile d'utiliser un projet qmake, mais il ne s'agit pas nécessairement de la méthode standard pour distribuer un logiciel sur une plateforme Linux. Le processus sert à titre d'exemple seulement, pour le développement. Quand vous créerez votre progiciel opérationnel, sans bogues, prenez le temps de préparer la distribution complète automagic (autoconf, automake) tel que décrit dans la prochaine section.
Compilons maintenant l'extension (ce n'est pas aussi simple que de taper gcc
myplugin.cpp
;). Voici un procédé simple : qmake de Qt (parce que certaines personnes hésitent à utiliser autoconf et automake en raison de leur complexité). Nota : vous devrez créer un fichier vide config.h
avant d'exécuter ces étapes.
#qmake -project
Maintenant que le fichier projet est créé, nous allons y apporter quelques petits changements.
###################################################################### # Automatically generated by qmake (1.06c) Sun Dec 14 13:32:11 2003 ###################################################################### #change TEMPLATE = app. Nous ne travaillons pas sur l'application, seulement sur l'extension TEMPLATE = lib INCLUDEPATH += . #Comme nous travaillons avec Scribus, nous avons besoin des inclusions de Scribus aussi. INCLUDEPATH += /home/subzero/devel/Scribus/include/Scribus/ #Et Scribus doit utiliser freetype2. #Donc nous devons le lier aussi. Utilisez les chemins retournés par ##freetype-config --cflags and --libs INCLUDEPATH += /usr/include/freetype2 LIBS += -lfreetype -lz # Entrée #crée un fichier config.h vide HEADERS += myplugin.h config.h SOURCES += myplugin.cpp
Après ces changements, vous êtes prêt à compiler
#qmake #make
Exécuter Qmake crée le Makefile et, en l'exécutant, vous compilez votre extension.
Ensuite : Copiez seulement les fichiers *so* dans le répertoire d'extensions de Scribus et lancez Scribus. Vous lirez "Do Nothing Plugin" dans le menu Extra.
Il est clair que vous devez utiliser une autre méthode pour distribuer votre code aux autres utilisateurs - certains utilisent les fichiers autogénérés qmake pro, d'autres, la combinaison autoconf/automake.
Qmake est facile à utiliser et convient bien à un développement rapide, mais il y a une manière standard de compiler ou de distribuer un logiciel pour Linux, *BSD, etc. : autoconf et automake. Nous désignerons ces deux programmes sous l'acronyme automagic dans le texte qui suit.
Pour utiliser automagic avec succès, vous aurez besoin d'un pentagramme dessiné à la craie sur le sol et orienté au nord (Carrefour, 2€), d'un costume de diablotin rouge et noir (Hugo Boss, 2000€) et d'un pingouin sacrifié sur l'autel domestique (une heure de frayeur au zoo le plus proche). Ce n'était qu'une blague... ne faites pas de mal aux mignons pingouins, ce n'est pas nécessaire!!
Téléchargez l'exemple donothingplugin-1.0.tar.gz
à partir de http://docs.scribus.net, décomprimez-le et parcourez son contenu.
Quand vous accédez au répertoire principal, vous apercevez beaucoup de fichiers et de répertoires. Attention : Ne changez rien dans le répertoire admin. Ce contenu vous est INTERDIT!
Puisque vous avez lu la documentation d'automagic (sûrement), vous savez que chaque répertoire de votre projet contient un fichier important appelé Makefile.am
. Voici un court exemple commenté :
# indique où l'extension sera installée pluginsdir = $(prefix)/lib/scribus/plugins # spécifie les inclusions additionnelles pour la compilation AM_CPPFLAGS = -I$(prefix)/include/scribus # spécifie les répertoires à parcourir (avec les sous-niveaux) SUBDIRS = translation doc # nom de l'extension = librairie plugins_LTLIBRARIES = libscribusvlna.la # join toutes les inclusions INCLUDES = $(LIBFREETYPE_CFLAGS) $(all_includes) # divers relatifs à la librairie - symlinks, etc. libscribusvlna_la_LDFLAGS = -version-info 0:0:0 libscribusvlna_la_METASOURCES = AUTO # # liste des fichiers source de votre projet libscribusvlna_la_SOURCES = frame.cpp selection.cpp vlnadialog.cpp vlnapage.cpp svlna.cpp EXTRA_DIST = frame.cpp selection.cpp svlna.cpp vlnadialog.cpp vlnapage.cpp frame.h / selection.h svlna.h vlnadialog.h vlnapage$ # comment compiler KDE_OPTIONS = qtonly AM_LDFLAGS = -s $(LIBFREETYPE_LIBS)
Pour récapituler : Si vous prenez le fichier donothingplugin-1.0.tar.gz
(si vous le renommez, bien sûr) et si vous analysez le contenu des fichiers Makefile.am
, vous obtiendrez un progiciel opérationnel.
Il reste une dernière chose à faire. Vous devez aussi spécifier la structure de répertoire dans le fichier configure.in
du répertoire racine du projet :
AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([svlna/Makefile]) AC_CONFIG_FILES([svlna/translation/Makefile]) AC_CONFIG_FILES([svlna/doc/Makefile])
Et maintenant, comment ça marche?
Premièrement lancez make -f Makefile.dist
dans le répertoire racine. Les modèles
de Makefile.in
sont créés (comme par magie).
Ensuite, ./configure ; make ; make install
devrait fonctionnner pour vous. Profitez-en.
À ce stade, vous devriez lire scplugin.h
et comprendre le texte d'aide. Pour des précisions sur le fonctionnement du système d'extensions ici. Surtout, vous apprendrez la procédure en lisant les autres extensions et le code central de Scribus.
Scribus fournit une API de préférences pour les développeurs d'extensions qui permet de conserver les données entre les démarrages de Scribus. Il y a deux types de formats disponibles : Paires "clé-valeur" et Tables.
Tout d'abord, vous devrez obtenir l'objet PrefsContext
pour votre extension. Ensuite, vous pouvez extraire de PrefsContext
une valeur de clé spécifique ou vous pouvez solliciter PrefsTable
par son nom. Voici un court exemple qui utilise les paires clé-valeur.
#include <prefsfile.h> #include <prefscontext.h> extern PrefsFile* prefsFile; PrefsContext *myPluginPrefs = prefsFile->getPluginContext("MyPlugin"); // la valeur par défaut 1 sera utilisée si "i" n'existe pas déjà int i = myPluginPrefs->getInt("i"); // la valeur par défaut "chien" sera utilisée si "s" n'existe pas QString s = myPluginPrefs->get("s", "chien"); myPluginPrefs->set("i", 221); myPluginPrefs->set("s", "chat");
Le code source de Scribus n'est pas documenté en détail. Beaucoup d'efforts sont déployés pour corriger la situation, mais étant donné la taille du code, cela prend du temps. Essayez de suivre l'évolution en vous basant sur les fichiers d'en-tête et sur le code. En cas de doute, n'hésitez pas à consulter le canal IRC ou à poser des questions via la liste de diffusion, et vous obtiendrez probablement une réponse. Soyezpatient, car nous ne sommes pas toujours disponibles ou présents sur IRC.
Si vous souhaitez améliorer la documentation ou corriger l'API de génération doxygen api, nous vous en saurons gré.
Il est important de noter que l'accès au coeur de l'application Scribus passe par l'aide du pointeur statique global ScApp
, déclaré dans scribus.h
. Attention à la confusion : c'est aussi une sous-classe de QMainWindow.
Vous pouvez également aller à la sous-classe QApplication utilisée comme ScQApp
à partir de scribusapp.h
.
Certains sous-systèmes majeurs sont des classes uniques qui sont accessibles via ClassName::instance() . Il y a par exemple PluginManager
,
ScPaths
, ainsi qu'un nombre croissant d'autres classes. L'avantage
de cette approche est de vous permettre d'interagir avec ces classes sans pénétrer dans les rouages de ScApp.